package jdklearning.nio;


import java.nio.ByteBuffer;

/**
 * https://blog.csdn.net/python8989/article/details/114078400
 * Buffer可以理解为是一个容器，用于存储数据，本质是个数组，存储的元素类型是基本类型。
 *无论是发送还是读取Channel中的数据，都必须先置入Buffer。
 * java.nio.Buffer是一个抽象类，子类包括有除boolean外其他所有基本类型的XxBuffer，最常用的是ByteBuffer。
 *
 * capacity：缓冲区的容量，表示该Buffer的最大数据容量，即最多可以存储多少数据。
 *
 * limit：限制位，标记position能够到达的最大位置，默认为缓冲区最后一位。
 *
 * position：操作位，指向即将操作位置，默认指向0。
 *
 * mark：可选标记位。默认不启用，Buffer允许直接将position定位到mark处。
 * mark <= position <= limit <= capacity
 *
 * 设置方法
 *
 * Buffer position(newPosition)： 将pos设置为newPosition。
 * Buffer limit(newLimit)：将limit设置为newLimit。
 * 数据操作
 *
 * Buffer reset：将pos置为mark的位置。
 * Buffer rewind：将pos置为0，取消设置的mark。
 * Buffer flip: 将limit置pos位置，pos置0。
 * Buffer clear：将position置为0，limit置为cap。
 *
 *
 * @author shenenlu 2021年03月08日 下午16:21:49
 */
public class ByteBufferLearning {

    public static void bufferOverflowTest(){
        // 创建 byteBuffer  allocate指定底层数组长度
        ByteBuffer byteBuffer = ByteBuffer.allocate(10);
        // 添加数据
        byteBuffer.put("summerDay11111111111".getBytes());
    }


    public static void byteBufferTest(){
        // 创建 byteBuffer  allocate指定底层数组长度
        ByteBuffer byteBuffer = ByteBuffer.allocate(10);

        // 添加数据
        byteBuffer.put("summerDay".getBytes());

        // 获取操作位的位置pos = 9
        System.out.println(byteBuffer.position());

        // 如果我想遍历summerDay呢?哪里结束? limit = 10
        System.out.println(byteBuffer.limit());

        //反转缓冲区 可以利用flip()代替下面两步操作
        //将limit移到position的位置
        byteBuffer.limit(byteBuffer.position());

        //将pos移到0
        byteBuffer.position(0);

        // position < limit
        // 可以利用 hasRemaining代替判断pos和limit之间是否还有可处理元素。
//        while(byteBuffer.position() < byteBuffer.limit()){
        while( byteBuffer.hasRemaining() ){
            // 获取数据
            byte b = byteBuffer.get();
            System.out.println((char)b);
        }
    }

    /**
     * 写入数据后调用,limit = position, position = 0,开始读数据
     */
    public static void flip(){
        // 如果数据已知,可以使用wrap方法创建ByteBuffer
        ByteBuffer byteBuffer = ByteBuffer.allocate(10);
        System.out.println( byteBuffer.position());
        byteBuffer.put( "summerDay".getBytes());
        System.out.println( byteBuffer.position());
        byteBuffer.flip();
        System.out.println( byteBuffer.position());
        while ( byteBuffer.hasRemaining()){
            System.out.print( (char)byteBuffer.get());
        }
    }


    public static void markAndRest(){
        ByteBuffer byteBuffer = ByteBuffer.allocate(10);
        System.out.println( byteBuffer.position());
        byteBuffer.put( "01234567".getBytes());
        byteBuffer.flip();
        int a = 0;
        int b;
        while( byteBuffer.hasRemaining() ){
            int c = byteBuffer.get();
            if(byteBuffer.position()==3){
                byteBuffer.mark();
            }
            if(byteBuffer.position()==4){
                a = c;
            }
            if( byteBuffer.position()==5 ){
                b = c;
                try {
                    System.out.println(a + b);
                    throw new RuntimeException("主动抛出");
                } catch (Exception e) {
                    byteBuffer.reset();
                }
            }
        }
    }



    public static void wrap(){
        // 如果数据已知,可以使用wrap方法创建ByteBuffer
        ByteBuffer byteBuffer = ByteBuffer.wrap("summerDay".getBytes());
        System.out.println( byteBuffer.position());
        // 获取底层字节数组
        byte[] array = byteBuffer.array();
        System.out.println(new String(array));
        System.out.println( byteBuffer.position());
        while ( byteBuffer.hasRemaining()){
            System.out.print( (char)byteBuffer.get());
        }
    }

    public static void main(String[] args) {
//        flip();
//        markAndRest();

        System.out.println((int)'1');

        // 创建 byteBuffer  allocate指定底层数组长度
//        ByteBuffer byteBuffer = ByteBuffer.allocate(10);
//        System.out.println(byteBuffer.position());  //0
//        System.out.println(byteBuffer.limit());  //10
//
//        byteBuffer.put((byte) 1);
//
//        System.out.println(byteBuffer.position()); //1
//        System.out.println(byteBuffer.get()); //0
//
//        byteBuffer.rewind();
//
//        System.out.println(byteBuffer.position()); //1
//        System.out.println(byteBuffer.get()); //0
    }

}
